package il.technion.cs236369.proxy;


import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import javax.net.ServerSocketFactory;

import org.apache.http.HttpException;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.DefaultHttpResponseFactory;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpProcessor;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.protocol.HttpRequestHandlerRegistry;
import org.apache.http.protocol.HttpService;
import org.apache.http.protocol.ImmutableHttpProcessor;

public class HttpServer
{
	private HttpParams m_params;
	private HttpService m_service;
	
	private ServerSocket m_serverSocket;
	private RequestHandler m_handler;

	// set up the basic parameters of an http service
	private void setupHttpService(HttpRequestHandler handler) 
	{
		HttpProcessor processor = new ImmutableHttpProcessor(new HttpResponseInterceptor[] {});

		HttpRequestHandlerRegistry registry = new HttpRequestHandlerRegistry();
		registry.register("*", handler);

		m_params = new BasicHttpParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000)
				.setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024)
				.setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false)
				.setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
				.setParameter(CoreProtocolPNames.ORIGIN_SERVER, "HttpComponents/1.1");
		
		m_service = new HttpService(processor,
									new DefaultConnectionReuseStrategy(),
									new DefaultHttpResponseFactory(), 
									registry, 
									m_params);
	}

	public HttpServer(ServerSocketFactory serverSocketFactory, 
						   int port, RequestHandler handler) throws IOException
	{
		m_serverSocket = serverSocketFactory.createServerSocket(port);
		m_handler = handler;
		setupHttpService(handler);
	}

	// process a new request
	public void getNewHttpRequest() throws IOException, HttpException
	{
		Socket socket = m_serverSocket.accept();		
		
		try 
		{
			DefaultHttpServerConnection serverConnection = new DefaultHttpServerConnection();
			
			serverConnection.bind(socket, m_params);
			HttpContext context = new BasicHttpContext(null);
			
			m_service.handleRequest(serverConnection, context);
			m_handler.closeConnections();
		} 
		catch (Exception e) 
		{
			e.printStackTrace();
		} 
	}

}
